package com.ehome.poct.terminal.service;

import cn.hutool.core.lang.UUID;
import com.ehome.context.thread.UserThreadLocal;
import com.ehome.core.page.PageInfo;
import com.ehome.exception.BizException;
import com.ehome.poct.core.api.common.DomainBizCode;
import com.ehome.poct.core.api.dto.order.*;
import com.ehome.poct.core.api.dto.report.PriceProfitDTO;
import com.ehome.poct.core.api.dto.report.ProfitDTO;
import com.ehome.poct.core.api.feign.PromotionBundlePriceProfitConfFeginClient;
import com.ehome.poct.core.api.feign.TestStripPriceProfitClient;
import com.ehome.poct.core.api.feign.TestStripPriceProfitSchemeFeignClient;
import com.ehome.poct.core.api.feign.TestStripPriceProfitSchemeOperateRecordFeginClient;
import com.ehome.poct.core.api.vo.order.DetectionVO;
import com.ehome.poct.core.api.vo.order.ProfitVO;
import com.ehome.poct.core.api.vo.order.TestStripPriceProfitSchemeOperateRecordVO;
import com.ehome.poct.core.api.vo.order.TestStripPriceProfitSchemeVO;
import com.ehome.poct.terminal.api.dto.PriceProfitAbleDTO;
import com.ehome.poct.terminal.api.fegin.UserManageFegin;
import com.ehome.poct.core.api.vo.PriceProfitVO;
import com.ehome.poct.core.api.vo.ProfitNameVO;
import com.ehome.poct.terminal.mapping.TestConfStripMapping;
import com.ehome.poct.terminal.mapping.TestStripPriceProfitMapping;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @author muqiu
 */
@Service
@AllArgsConstructor
@Slf4j
public class PriceProfitSchemeService {

    private final TestStripPriceProfitSchemeFeignClient testStripPriceProfitSchemeFeignClient;
    private final TestStripPriceProfitClient testStripPriceProfitClient;
    private final TestConfStripMapping testConfStripMapping;
    private final TestStripPriceProfitMapping testStripPriceProfitMapping;
    private final UserManageFegin userManageFegin;
    private final TestStripPriceProfitSchemeOperateRecordFeginClient testStripPriceProfitSchemeOperateRecordFeginClient;
    private final PromotionBundlePriceProfitConfFeginClient promotionBundlePriceProfitConfFeginClient;
    //肺支肺衣联合检测
    private final Map<Integer, String> U_MPIGM_CPNIGM_REPORT = Map.ofEntries(Map.entry(6, "MPIGM_REPORT")
            , Map.entry(17, "CPNIGM_REPORT")
            , Map.entry(50, "U_MPIGM_CPNIGM_REPORT"));
    //肺支总抗肺衣联合检测
    private final Map<Integer, String> U_MP_AB_CPNIGM_REPORT = Map.ofEntries(Map.entry(9, "MPAB_REPORT")
            , Map.entry(17, "CPNIGM_REPORT")
            , Map.entry(51, "U_MP_AB_CPNIGM_REPORT"));


    public PageInfo<PriceProfitVO> list(PriceProfitSchemeDTO dto) {
        var profitSchemes  = testStripPriceProfitSchemeFeignClient.pageQuery(dto);
        var profitSchemesNums = userManageFegin.queryPriceProfitNums(profitSchemes.getList().stream().map(TestStripPriceProfitSchemeVO::getTestStripPriceProfitSchemeId).collect(Collectors.toList())).getData();
        profitSchemes.getList().forEach(r -> {
            testStripPriceProfitMapping.to(r,profitSchemesNums.stream().filter(p -> p.getPriceProfitId().equals(r.getTestStripPriceProfitSchemeId())).findFirst().orElse(null));
        });
        return testStripPriceProfitMapping.to(profitSchemes);
    }

    public List<DetectionVO> getDetections() {
        var list = testConfStripMapping.to(testStripPriceProfitClient.getDetections());
        list.add(new DetectionVO().setStripTypeCode(100).setTestConfStripName("血常规三分类检测").setTestConfigDisplayName("三分类血常规检测"));
        return list;
    }

    public void addProfit(PriceProfitDTO dto) {
        //校验数据是否齐全
        checkData(dto.getProfitList());
        if(dto.getTestStripPriceProfitSchemeId() == null) {
            var profitSchemeVO = testStripPriceProfitSchemeFeignClient.addProfit(createTestStripPriceProfitSchemeDTO(dto.getPriceProfitSchemeName()));
            dto.getProfitList().forEach(r -> {
                //捆绑促销活动
                bundlePriceProfitConf(r,dto.setTestStripPriceProfitSchemeId(profitSchemeVO.getTestStripPriceProfitSchemeId()));
                testStripPriceProfitClient.addProfit(createTestStripPriceProfitDTO(profitSchemeVO.getTestStripPriceProfitSchemeId(), r));
            });
            //保存操作记录
            saveRecord("新增",profitSchemeVO.getTestStripPriceProfitSchemeId(),dto.getPriceProfitSchemeName());
        }else {
            //校验是否存在相同的价格方案
            final var testStripPriceProfitSchemeDTO = testStripPriceProfitSchemeFeignClient.list(dto.getPriceProfitSchemeName()).stream().findFirst().orElse(null);
            if(testStripPriceProfitSchemeDTO != null && !testStripPriceProfitSchemeDTO.getTestStripPriceProfitSchemeId().equals(dto.getTestStripPriceProfitSchemeId())){
                throw new BizException(DomainBizCode.PRICE_SCHEME_NAME_ALREADY_EXISTS);
            }
            testStripPriceProfitSchemeFeignClient.updateById(dto.getTestStripPriceProfitSchemeId(),new TestStripPriceProfitSchemeDTO().setPriceProfitSchemeName(dto.getPriceProfitSchemeName()));
            //删除原有价格项
            testStripPriceProfitClient.deleteProfitById(dto.getTestStripPriceProfitSchemeId());
            //删除原有捆绑促销活动
            var priceConf = promotionBundlePriceProfitConfFeginClient.list(new PromotionBundlePriceProfitConfDTO().setTestStripPriceProfitSchemeId(dto.getTestStripPriceProfitSchemeId()));
            priceConf.forEach(p -> promotionBundlePriceProfitConfFeginClient.delete(p.getPromotionBundlePriceProfitConfId()));
            dto.getProfitList().forEach(r -> {
                //捆绑促销活动
                bundlePriceProfitConf(r,dto);
                testStripPriceProfitClient.addProfit(createTestStripPriceProfitDTO(dto.getTestStripPriceProfitSchemeId(), r));
            });
            //保存操作记录
            saveRecord("编辑",dto.getTestStripPriceProfitSchemeId(),dto.getPriceProfitSchemeName());
        }
    }

    private void checkData(List<ProfitDTO> profitList) {
        profitList.forEach(r -> {
            //肺支肺衣相关
            if(r.getStripTypeCode() == 50) {
                checkData(U_MPIGM_CPNIGM_REPORT,profitList);
            }
            if(r.getStripTypeCode() == 51){
                checkData(U_MP_AB_CPNIGM_REPORT,profitList);
            }
        });
    }

    private void checkData(Map<Integer,String> code,List<ProfitDTO> profitList){
        code.forEach((key, value) -> {
            var profitDTO = profitList.stream().filter(i -> i.getStripTypeCode().equals(key)).findFirst().orElse(null);
            if (profitDTO == null) {
                throw new BizException(123567, "捆绑促销活动，必须配置相应单项检测价格");
            }
        });
    }

    private void bundlePriceProfitConf(ProfitDTO r,PriceProfitDTO dto) {
        //肺支肺衣相关
        if(r.getStripTypeCode() == 50) {
            createPromotionBundlePriceProfitConf(U_MPIGM_CPNIGM_REPORT,dto,c -> c.forEach(promotionBundlePriceProfitConfFeginClient::add));
        }
        if(r.getStripTypeCode() == 51){
            createPromotionBundlePriceProfitConf(U_MP_AB_CPNIGM_REPORT,dto,c -> c.forEach(promotionBundlePriceProfitConfFeginClient::add));
        }
    }

    private void createPromotionBundlePriceProfitConf(Map<Integer,String> code, PriceProfitDTO dto, Consumer<List<PromotionBundlePriceProfitConfDTO>> fun){
        List<PromotionBundlePriceProfitConfDTO> list = new ArrayList<>();
        code.forEach((key, value) -> {
            var profitDTO = dto.getProfitList().stream().filter(i -> i.getStripTypeCode().equals(key)).findFirst().orElse(null);
            var name = dto.getPriceProfitSchemeName();
            if (profitDTO == null) {
                throw new BizException(123567, "捆绑促销活动，必须配置相应单项检测价格");
            }
            list.add(new PromotionBundlePriceProfitConfDTO().setProductCombineCode(code.containsKey(50) ? "0617" : "0917")
                    .setReportCode(value).setSalePrice(profitDTO.getSalePrice())
                    .setPriceProfitSchemeName(name).setRealSalePrice(key == 50 || key == 51 ? profitDTO.getSalePrice() : new BigDecimal("0"))
                    .setStripTypeCode(key).setEffectiveStart(LocalDateTime.now()).setEffectiveEnd(LocalDateTime.now().plusYears(3))
                    .setEffectiveStatus(0).setNeedProfit(0).setTestStripPriceProfitSchemeId(dto.getTestStripPriceProfitSchemeId()));
        });
        fun.accept(list);
    }

    private void saveRecord(String operateType,Long profitId,String priceProfitSchemeName){
        final var user = UserThreadLocal.getUser();
        testStripPriceProfitSchemeOperateRecordFeginClient.saveRecord(new TestStripPriceProfitSchemeOperateRecordDTO().setOperater(user.getName()).setAccount(user.getMobilePhone() != null ? Long.valueOf(user.getMobilePhone()) : null).setOperateType(operateType).setProfitId(profitId).setProfitName(priceProfitSchemeName));
    }

    private TestStripPriceProfitDTO createTestStripPriceProfitDTO(Long testStripPriceProfitSchemeId, ProfitDTO r) {
        return testStripPriceProfitMapping.to(testStripPriceProfitSchemeId,r);
    }

    private TestStripPriceProfitSchemeDTO createTestStripPriceProfitSchemeDTO(String priceProfitSchemeName) {
        //校验是否存在相同的价格方案
        if(!testStripPriceProfitSchemeFeignClient.list(priceProfitSchemeName).isEmpty()){
            throw new BizException(DomainBizCode.PRICE_SCHEME_NAME_ALREADY_EXISTS);
        }
        return new TestStripPriceProfitSchemeDTO().setPriceProfitSchemeName(priceProfitSchemeName)
                .setOwnerUserid((long)1).setLevel(3).setStatus(0).setFirstAgentDisplayName("省总分成")
                .setSecondAgentDispalyName("地总分成").setThirdAgentDisplayName("业务员分成").setClinicFiledDisplayName("诊所利润")
                .setConpanyFileDisplayName("伊鸿利润").setSchemeMd5(UUID.randomUUID().toString());
    }

    public ProfitVO getById(Long id) {
        final var profitSchemeVO = testStripPriceProfitSchemeFeignClient.getById(id);
        final var testStripPriceProfitVOList = testStripPriceProfitClient.list(new TestStripPriceProfitDTO().setTestStripPriceProfitSchemeId(profitSchemeVO.getTestStripPriceProfitSchemeId()));
        final var priceProfit = testStripPriceProfitMapping.to(profitSchemeVO.getPriceProfitSchemeName(),testStripPriceProfitVOList);
        final var detections = getDetections();
        var codes = priceProfit.getProfitList().stream().map(ProfitDTO::getStripTypeCode).collect(Collectors.toList());
        return new ProfitVO(detections.stream().filter(r -> !codes.contains(r.getStripTypeCode())).collect(Collectors.toList()),priceProfit);
    }

    public void updateStatus(PriceProfitAbleDTO priceProfitAbleDTO) {
        for (Long id : priceProfitAbleDTO.getIds()) {
            testStripPriceProfitSchemeFeignClient.updateById(id,new TestStripPriceProfitSchemeDTO().setStatus(priceProfitAbleDTO.getStatus()));
            //保存操作记录
            saveRecord(priceProfitAbleDTO.getStatus() == 0 ? "启用" : "禁用",id, testStripPriceProfitSchemeFeignClient.getById(id).getPriceProfitSchemeName());
        }
    }


    public PageInfo<TestStripPriceProfitSchemeOperateRecordVO> getOperateRecord(OperateRecordDTO dto) {
        return testStripPriceProfitSchemeOperateRecordFeginClient.pageQuery(dto);
    }

    public List<ProfitNameVO> getByIdOrProfitName(String idOrProfitName) {
        //模糊查询价格方案名称
        final var profitSchemeByName = testStripPriceProfitSchemeFeignClient.list(new TestStripPriceProfitSchemeDTO().setPriceProfitSchemeName(idOrProfitName).setIsActivity(0));
        ArrayList<TestStripPriceProfitSchemeVO> list = new ArrayList<>(profitSchemeByName);
        if(StringUtils.isNumeric(idOrProfitName)){
            final var profitSchemeById = testStripPriceProfitSchemeFeignClient.getById(Long.valueOf(idOrProfitName));
            if(profitSchemeById != null) {
                list.add(profitSchemeById);
            }
        }
        return testStripPriceProfitMapping.to(list);
    }
}
